package com.canbot.u05.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.canbot.u05.R;

import java.util.ArrayList;

/**
 * 自定义的时间选择器
 *
 * @author sxzhang
 */
public class WheelView extends View {

        /**
         * 控件宽度
         */
        private float controlWidth;

        /**
         * 控件高度
         */
        private float controlHeight;

        /**
         * 是否滑动中
         */
        private boolean isScrolling = false;

        /**
         * 选择的内容
         */
        private ArrayList<ItemObject> itemList = new ArrayList<>();

        /**
         * 设置数据
         */
        private ArrayList<String> dataList = new ArrayList<>();

        /**
         * 按下的坐标
         */
        private int downY;

        /**
         * 按下的时间
         */
        private long downTime = 0;

        /**
         * 短促移动
         */
        private long goonTime = 200;

        /**
         * 短促移动距离
         */
        private int goonDistance = 100;

        /**
         * 画线画笔
         */
        private Paint linePaint;

        /**
         * 线的默认颜色
         */
        private int lineColor = 0xff000000;

        /**
         * 线的默认宽度
         */
        private float lineHeight = 2f;

        /**
         * 默认字体
         */
        private float normalFont = 14.0f;

        /**
         * 选中的时候字体
         */
        private float selectedFont = 22.0f;

        /**
         * 单元格高度
         */
        private int unitHeight = 50;

        /**
         * 显示多少个内容
         */
        private int itemNumber = 7;

        /**
         * 默认字体颜色
         */
        private int normalColor = 0xff000000;

        /**
         * 选中时候的字体颜色
         */
        private int selectedColor = 0xffff0000;

        /**
         * 蒙板高度
         */
        private float maskHeight = 48.0f;

        /**
         * 选择监听
         */
        private OnSelectListener onSelectListener;

        /**
         * 是否可用
         */
        private boolean isEnable = true;

        /**
         * 刷新界面
         */
        private static final int REFRESH_VIEW = 0x001;

        /**
         * 移动距离
         */
        private static final int MOVE_NUMBER = 5;

        /**
         * 是否允许选空
         */
        private boolean noEmpty = true;

        /**
         * 正在修改数据，避免ConcurrentModificationException异常
         */
        private boolean isClearing = false;

        public WheelView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
                init(context, attrs);
                initData();
        }

        public WheelView(Context context, AttributeSet attrs) {
                super(context, attrs);
                init(context, attrs);
                initData();
        }

        public WheelView(Context context) {
                super(context);
                initData();
        }

        /**
         * 初始化，获取设置的属性
         *
         * @param context
         * @param attrs
         */
        private void init(Context context, AttributeSet attrs) {

                TypedArray attribute = context.obtainStyledAttributes(attrs, R.styleable.WheelView);
                unitHeight = (int) attribute.getDimension(R.styleable.WheelView_unitHeight, unitHeight);
                itemNumber = attribute.getInt(R.styleable.WheelView_itemNumber, itemNumber);

                normalFont = attribute.getDimension(R.styleable.WheelView_normalTextSize, normalFont);
                selectedFont = attribute.getDimension(R.styleable.WheelView_selectedTextSize, selectedFont);
                normalColor = attribute.getColor(R.styleable.WheelView_normalTextColor, normalColor);
                selectedColor = attribute.getColor(R.styleable.WheelView_selectedTextColor, selectedColor);

                lineColor = attribute.getColor(R.styleable.WheelView_lineColor, lineColor);
                lineHeight = attribute.getDimension(R.styleable.WheelView_lineHeight, lineHeight);

                maskHeight = attribute.getDimension(R.styleable.WheelView_maskHeight, maskHeight);
                noEmpty = attribute.getBoolean(R.styleable.WheelView_noEmpty, true);
                isEnable = attribute.getBoolean(R.styleable.WheelView_isEnable, true);

                attribute.recycle();

                controlHeight = itemNumber * unitHeight;
        }

        /**
         * 初始化数据
         */
        private void initData() {
                isClearing = true;
                itemList.clear();
                for (int i = 0; i < dataList.size(); i++) {
                        ItemObject itemObject = new ItemObject();
                        itemObject.id = i;
                        itemObject.itemText = dataList.get(i);
                        itemObject.x = 0;
                        itemObject.y = i * unitHeight;
                        itemList.add(itemObject);
                }
                isClearing = false;
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                controlWidth = getMeasuredWidth();
                if (controlWidth != 0) {
                        setMeasuredDimension(getMeasuredWidth(), itemNumber * unitHeight);
                }
        }

        @Override
        protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);

                drawLine(canvas);
                drawList(canvas);
                drawMask(canvas);
        }

        /**
         * 绘制线条
         *
         * @param canvas
         */
        private void drawLine(Canvas canvas) {

                if (linePaint == null) {
                        linePaint = new Paint();
                        linePaint.setColor(lineColor);
                        linePaint.setAntiAlias(true);
                        linePaint.setStrokeWidth(lineHeight);
                }

                canvas.drawLine(0, controlHeight / 2 - unitHeight / 2 + lineHeight,
                        controlWidth, controlHeight / 2 - unitHeight / 2 + lineHeight, linePaint);
                canvas.drawLine(0, controlHeight / 2 + unitHeight / 2 - lineHeight,
                        controlWidth, controlHeight / 2 + unitHeight / 2 - lineHeight, linePaint);
        }

        private synchronized void drawList(Canvas canvas) {
                if (isClearing)
                        return;
                try {
                        for (ItemObject itemObject : itemList) {
                                itemObject.drawSelf(canvas, getMeasuredWidth());
                        }
                }
                catch (Exception e) {
                }
        }

        /**
         * 绘制遮盖板
         *
         * @param canvas
         */
        private void drawMask(Canvas canvas) {
                LinearGradient lg = new LinearGradient(0, 0, 0, maskHeight, 0x00f2f2f2,
                        0x00f2f2f2, Shader.TileMode.MIRROR);
                Paint paint = new Paint();
                paint.setShader(lg);
                canvas.drawRect(0, 0, controlWidth, maskHeight, paint);

                LinearGradient lg2 = new LinearGradient(0, controlHeight - maskHeight,
                        0, controlHeight, 0x00f2f2f2, 0x00f2f2f2, Shader.TileMode.MIRROR);
                Paint paint2 = new Paint();
                paint2.setShader(lg2);
                canvas.drawRect(0, controlHeight - maskHeight, controlWidth,
                        controlHeight, paint2);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
                if (!isEnable)
                        return true;
                int y = (int) event.getY();
                switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                                isScrolling = true;
                                downY = (int) event.getY();
                                downTime = System.currentTimeMillis();
                                break;
                        case MotionEvent.ACTION_MOVE:
                                actionMove(y - downY);
                                onSelectListener();
                                break;
                        case MotionEvent.ACTION_UP:
                                int move = Math.abs(y - downY);
                                // 判断这段时间移动的距离
                                if (System.currentTimeMillis() - downTime < goonTime && move > goonDistance) {
                                        goonMove(y - downY);
                                }
                                else {
                                        actionUp(y - downY);
                                        noEmpty();
                                        isScrolling = false;
                                }
                                break;
                        default:
                                break;
                }
                return true;
        }

        /**
         * 继续移动一定距离
         */
        private synchronized void goonMove(final int move) {
                new Thread(new Runnable() {

                        @Override
                        public void run() {
                                int distance = 0;
                                while (distance < unitHeight * MOVE_NUMBER) {
                                        try {
                                                Thread.sleep(5);
                                        }
                                        catch (InterruptedException e) {
                                                e.printStackTrace();
                                        }
                                        actionThreadMove(move > 0 ? distance : distance * (-1));
                                        distance += 10;

                                }
                                actionUp(move > 0 ? distance - 10 : distance * (-1) + 10);
                                noEmpty();
                        }
                }).start();
        }

        /**
         * 不能为空，必须有选项
         */
        private void noEmpty() {
                if (!noEmpty)
                        return;
                for (ItemObject item : itemList) {
                        if (item.isSelected())
                                return;
                }
                int move = (int) itemList.get(0).moveToSelected();
                if (move < 0) {
                        defaultMove(move);
                }
                else {
                        defaultMove((int) itemList.get(itemList.size() - 1)
                                .moveToSelected());
                }
                for (ItemObject item : itemList) {
                        if (item.isSelected()) {
                                if (onSelectListener != null)
                                        onSelectListener.endSelect(WheelView.this, item.id, item.itemText);
                                break;
                        }
                }
        }

        /**
         * 移动的时候
         *
         * @param move
         */
        private void actionMove(int move) {
                for (ItemObject item : itemList) {
                        item.move(move);
                }
                invalidate();
        }

        /**
         * 移动，线程中调用
         *
         * @param move
         */
        private void actionThreadMove(int move) {
                for (ItemObject item : itemList) {
                        item.move(move);
                }
                Message rMessage = new Message();
                rMessage.what = REFRESH_VIEW;
                handler.sendMessage(rMessage);
        }

        /**
         * 松开的时候
         *
         * @param move
         */
        private void actionUp(int move) {
                int newMove = 0;
                if (move > 0) {
                        for (int i = 0; i < itemList.size(); i++) {
                                if (itemList.get(i).isSelected()) {
                                        newMove = (int) itemList.get(i).moveToSelected();
                                        if (onSelectListener != null)
                                                onSelectListener.endSelect(WheelView.this, itemList.get(i).id,
                                                        itemList.get(i).itemText);
                                        break;
                                }
                        }
                }
                else {
                        for (int i = itemList.size() - 1; i >= 0; i--) {
                                if (itemList.get(i).isSelected()) {
                                        newMove = (int) itemList.get(i).moveToSelected();
                                        if (onSelectListener != null)
                                                onSelectListener.endSelect(WheelView.this, itemList.get(i).id,
                                                        itemList.get(i).itemText);
                                        break;
                                }
                        }
                }
                for (ItemObject item : itemList) {
                        item.newY(move + 0);
                }
                slowMove(newMove);
                Message rMessage = new Message();
                rMessage.what = REFRESH_VIEW;
                handler.sendMessage(rMessage);

        }

        /**
         * 缓慢移动
         *
         * @param move
         */
        private synchronized void slowMove(final int move) {
                new Thread(new Runnable() {

                        @Override
                        public void run() {
                                // 判断正负
                                int m = move > 0 ? move : move * (-1);
                                int i = move > 0 ? 1 : (-1);
                                // 移动速度
                                int speed = 1;
                                while (true) {
                                        m = m - speed;
                                        if (m <= 0) {
                                                for (ItemObject item : itemList) {
                                                        item.newY(m * i);
                                                }
                                                Message rMessage = new Message();
                                                rMessage.what = REFRESH_VIEW;
                                                handler.sendMessage(rMessage);
                                                try {
                                                        Thread.sleep(2);
                                                }
                                                catch (InterruptedException e) {
                                                        e.printStackTrace();
                                                }
                                                break;
                                        }
                                        for (ItemObject item : itemList) {
                                                item.newY(speed * i);
                                        }
                                        Message rMessage = new Message();
                                        rMessage.what = REFRESH_VIEW;
                                        handler.sendMessage(rMessage);
                                        try {
                                                Thread.sleep(2);
                                        }
                                        catch (InterruptedException e) {
                                                e.printStackTrace();
                                        }
                                }
                                for (ItemObject item : itemList) {
                                        if (item.isSelected()) {
                                                if (onSelectListener != null)
                                                        onSelectListener.endSelect(WheelView.this, item.id, item.itemText);
                                                break;
                                        }
                                }

                        }
                }).start();
        }

        /**
         * 移动到默认位置
         *
         * @param move
         */
        private void defaultMove(int move) {
                for (ItemObject item : itemList) {
                        item.newY(move);
                }
                Message rMessage = new Message();
                rMessage.what = REFRESH_VIEW;
                handler.sendMessage(rMessage);
        }

        /**
         * 滑动监听
         */
        private void onSelectListener() {
                if (onSelectListener == null)
                        return;
                for (ItemObject item : itemList) {
                        if (item.isSelected()) {
                                onSelectListener.selecting(item.id, item.itemText);
                        }
                }
        }

        /**
         * 设置数据 （第一次）
         *
         * @param data
         */
        public void setData(ArrayList<String> data) {
                this.dataList = data;
                initData();
        }

        /**
         * 重置数据
         *
         * @param data
         */
        public void refreshData(ArrayList<String> data) {
                setData(data);
                invalidate();
        }

        /**
         * 获取返回项 id
         *
         * @return
         */
        public int getSelected() {
                for (ItemObject item : itemList) {
                        if (item.isSelected())
                                return item.id;
                }
                return -1;
        }

        /**
         * 获取返回的内容
         *
         * @return
         */
        public String getSelectedText() {
                for (ItemObject item : itemList) {
                        if (item.isSelected())
                                return item.itemText;
                }
                return "";
        }

        /**
         * 是否正在滑动
         *
         * @return
         */
        public boolean isScrolling() {
                return isScrolling;
        }

        /**
         * 是否可用
         *
         * @return
         */
        public boolean isEnable() {
                return isEnable;
        }

        /**
         * 设置是否可用
         *
         * @param isEnable
         */
        public void setEnable(boolean isEnable) {
                this.isEnable = isEnable;
        }

        /**
         * 设置默认选项
         *
         * @param index
         */
        public void setDefault(int index) {
                if (index > itemList.size() - 1)
                        return;
                float move = itemList.get(index).moveToSelected();
                defaultMove((int) move);
        }

        /**
         * 获取列表大小
         *
         * @return
         */
        public int getListSize() {
                if (itemList == null)
                        return 0;
                return itemList.size();
        }

        /**
         * 获取某项的内容
         *
         * @param index
         * @return
         */
        public String getItemText(int index) {
                if (itemList == null)
                        return "";
                return itemList.get(index).itemText;
        }

        /**
         * 监听
         *
         * @param onSelectListener
         */
        public void setOnSelectListener(OnSelectListener onSelectListener) {
                this.onSelectListener = onSelectListener;
        }

        @SuppressLint("HandlerLeak")
        Handler handler = new Handler() {

                @Override
                public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        switch (msg.what) {
                                case REFRESH_VIEW:
                                        invalidate();
                                        break;
                                default:
                                        break;
                        }
                }

        };

        /**
         * 单条内容
         *
         * @author JiangPing
         */
        private class ItemObject {

                /**
                 * id
                 */
                public int id = 0;

                /**
                 * 内容
                 */
                public String itemText = "";

                /**
                 * x坐标
                 */
                public int x = 0;

                /**
                 * y坐标
                 */
                public int y = 0;

                /**
                 * 移动距离
                 */
                public int move = 0;

                /**
                 * 字体画笔
                 */
                private TextPaint textPaint;

                /**
                 * 字体范围矩形
                 */
                private Rect textRect;

                public ItemObject() {
                        super();
                }

                /**
                 * 绘制自身
                 *
                 * @param canvas         画板
                 * @param containerWidth 容器宽度
                 */
                public void drawSelf(Canvas canvas, int containerWidth) {

                        if (textPaint == null) {
                                textPaint = new TextPaint();
                                textPaint.setAntiAlias(true);
                        }

                        if (textRect == null)
                                textRect = new Rect();

                        // 判断是否被选择
                        if (isSelected()) {
                                textPaint.setColor(selectedColor);
                                // 获取距离标准位置的距离
                                float moveToSelect = moveToSelected();
                                moveToSelect = moveToSelect > 0 ? moveToSelect : moveToSelect * (-1);
                                // 计算当前字体大小
                                float textSize = normalFont
                                        + ((selectedFont - normalFont) * (1.0f - moveToSelect / (float) unitHeight));
                                textPaint.setTextSize(textSize);
                        }
                        else {
                                textPaint.setColor(normalColor);
                                textPaint.setTextSize(normalFont);
                        }

                        // 返回包围整个字符串的最小的一个Rect区域
                        itemText = (String) TextUtils.ellipsize(itemText, textPaint, containerWidth, TextUtils.TruncateAt.END);
                        textPaint.getTextBounds(itemText, 0, itemText.length(), textRect);
                        // 判断是否可视
                        if (!isInView())
                                return;

                        // 绘制内容
                        canvas.drawText(itemText, x + controlWidth / 2 - textRect.width() / 2,
                                y + move + unitHeight / 2 + textRect.height() / 2, textPaint);

                }

                /**
                 * 是否在可视界面内
                 *
                 * @return
                 */
                public boolean isInView() {
                        if (y + move > controlHeight || (y + move + unitHeight / 2 + textRect.height() / 2) < 0)
                                return false;
                        return true;
                }

                /**
                 * 移动距离
                 *
                 * @param _move
                 */
                public void move(int _move) {
                        this.move = _move;
                }

                /**
                 * 设置新的坐标
                 *
                 * @param _move
                 */
                public void newY(int _move) {
                        this.move = 0;
                        this.y = y + _move;
                }

                /**
                 * 判断是否在选择区域内
                 *
                 * @return
                 */
                public boolean isSelected() {
                        if ((y + move) >= controlHeight / 2 - unitHeight / 2 + lineHeight
                                && (y + move) <= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                                return true;
                        }
                        if ((y + move + unitHeight) >= controlHeight / 2 - unitHeight / 2 + lineHeight
                                && (y + move + unitHeight) <= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                                return true;
                        }
                        if ((y + move) <= controlHeight / 2 - unitHeight / 2 + lineHeight
                                && (y + move + unitHeight) >= controlHeight / 2 + unitHeight / 2 - lineHeight) {
                                return true;
                        }
                        return false;
                }

                /**
                 * 获取移动到标准位置需要的距离
                 */
                public float moveToSelected() {
                        return (controlHeight / 2 - unitHeight / 2) - (y + move);
                }
        }

        /**
         * 选择监听
         *
         * @author JiangPing
         */
        public interface OnSelectListener {

                /**
                 * 结束选择
                 *
                 * @param id
                 * @param text
                 */
                void endSelect(View view, int id, String text);

                /**
                 * 选中的内容
                 *
                 * @param id
                 * @param text
                 */
                void selecting(int id, String text);

        }

}
